#pragma once

#include "StdAfx.h"
#include "Watchdog.h"
#include "RomSet.h"
#include "State.h"
#include "video.h"
#include "input.h"
#include "sound.h"

//palette conversion macros
#define ConvertRGB24(rr,gg,bb) \
	(((rr) << 16) | ((gg) << 8) | (bb))

#define ConvertBBGGGRRR(dd) \
	(((0x21 * ((data >> 0) & 1)) + (0x47 * ((data >> 1) & 1)) + (0x97 * ((data >> 2) & 1))) << 16) | \
	(((0x21 * ((data >> 3) & 1)) + (0x47 * ((data >> 4) & 1)) + (0x97 * ((data >> 5) & 1))) << 8) | \
	((0x47 * ((data >> 6) & 1)) + (0x97 * ((data >> 7) & 1)))

#define InitNVRAM(nn,dd,ss)		\
	if(sNVRAM == 0)					\
		sNVRAM = new CNVRAM(nn,dd,ss);

#define MAX_CPUS			4

typedef struct LoadInfo_s		//where to load roms
	{
	u32 Flags;		//rom load flags
	u8 *Ptr;			//pointer to location of where to load the data
	} LoadInfo;

class CCPU;
class CMachine
{
protected:
	CRomSet *RomSet;								//pointer to loaded romset
	CVideo *Video;									//video interface
	CInput *Input;									//input interface
	CSound *Sound;									//sound interface
	list_c LoadInfoList;							//where to load rom information
	u8 InputData[4];
	u8 Dip[4];
public:
	CWatchdog *Watchdog;							//watchdog
	CNVRAM *sNVRAM;								//nvram class
	CCPU *CPU[MAX_CPUS];							//cpus used by a machine
public:
	CMachine();
	virtual ~CMachine();
	void SetVideo(CVideo *v){Video = v;}
	void SetInput(CInput *i){Input = i;}
	void SetSound(CSound *s){Sound = s;}
	void LoadROMs();
	void AddLoadInfo(u32 Flags,u8 *Ptr)
		{
		LoadInfo *li = new LoadInfo;

		li->Flags = Flags;
		li->Ptr = Ptr;
		LoadInfoList.add(li);
		}
	void ChangeLoadInfo(u32 Flags,u8 *Ptr)
		{
		int i;
		LoadInfo *l;

		for(i=0;i<LoadInfoList.num();i++)
			{
			l = (LoadInfo*)LoadInfoList.get(i);
			if(l && l->Flags == Flags)		//change this one
				{
				l->Ptr = Ptr;
				return;
				}
			}
		message("ChangeLoadInfo: Flags not matched, adding new entry\n");
		AddLoadInfo(Flags,Ptr);
		}
	void ProcessInput();
	virtual int Load(CRomSet *r);				//load romset into machine
	virtual int Init() = 0;
	virtual void Kill() = 0;
	virtual void Reset() = 0;					//reset machine
	virtual void Line(u32 mainc,u32 soundc,int irq) = 0;	//execute one line
	virtual void Frame() = 0;					//execute one frame
	virtual void SaveState(CState *s){}		//save state
	virtual void LoadState(CState *s){}		//load state
	virtual void SaveScores(){}				//save high scores
	virtual void LoadScores(){}				//load high scores
	virtual int FPS(){return(60);}			//60 fps is default
	CRomSet *GetRomSet(){return(RomSet);}
	virtual void BlitRotate(u8 *S,u32 *D,u32 *P);		//8bit blit helper
	virtual void BlitRotate16(u16 *S,u32 *D,u32 *P);	//16bit blit helper

	virtual int GetScanline(){return(0);};
};

#include "cpu/CPU.h"
